﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace TimeSheet
{
    public class Semana
    {
        public List<DateTime> Dias { get; set; }
        public int Numero { get; set; }
    }

    public partial class Default : System.Web.UI.Page
    {
        public List<TimesheetEntries> Tarefas
        {
            get { return Session["Tarefas"] == null ? null : (List<TimesheetEntries>)Session["Tarefas"]; }
            set { Session["Tarefas"] = value; }
        }

        public List<Semana> Semanas
        {
            get { return Session["Semanas"] == null ? null : (List<Semana>)Session["Semanas"]; }
            set { Session["Semanas"] = value; }
        }

        public Semana SemanaAtual
        {
            get { return Session["SemanaAtual"] == null ? null : (Semana)Session["SemanaAtual"]; }
            set { Session["SemanaAtual"] = value; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
                return;

            Inicializa();
        }

        private void Inicializa()
        {
            if (Session["UsuarioSelecionado"] == null)
            {
                var cookie = Request.Cookies["user_timesheet"];
                if (cookie != null)
                    Session["UsuarioSelecionado"] = cookie.Value;
            }

            txtData.Attributes.Add("placeholder", DateTime.Now.ToString("dd/MM/yyyy"));

            BindUsuarios();

            BindTimeSheet(true);
        }

        public void BindUsuarios()
        {
            var usuarios = NTimeSheet.ConsultarListaUsuarios();

            usuarios.Add(new Constants { ConstID = 99999, DisplayPart = "[Selecione]" });

            ddlUsuario.DataSource = usuarios.OrderBy(c => c.DisplayPart);
            ddlUsuario.DataTextField = "DisplayPart";
            ddlUsuario.DataValueField = "ConstID";
            ddlUsuario.DataBind();

            if (Session["UsuarioSelecionado"] == null)
                ddlUsuario.SelectedValue = "99999";
            else
                ddlUsuario.SelectedValue = Session["UsuarioSelecionado"].ToString();
        }

        public Panel DivClear()
        {
            Panel div = new Panel();
            div.Style.Add("clear", "both");

            return div;
        }

        public Panel AplicaEstilo(Panel div, string cor = "", string corLetra = "", string style = "")
        {
            if (!string.IsNullOrEmpty(style))
                div.CssClass = style;
            else
                div.CssClass = "item";
            if (!string.IsNullOrEmpty(cor))
                div.Style.Add("background-color", cor);
            if (!string.IsNullOrEmpty(corLetra))
                div.Style.Add("color", corLetra);
            return div;
        }

        public Semana GetSemana(DateTime dia, bool buscaSegunda = true)
        {
            var dias = new List<DateTime>();

            var segundaFeira = dia;

            if (buscaSegunda)
            {
                if (DateTime.Now.DayOfWeek == DayOfWeek.Tuesday)
                    segundaFeira = dia.AddDays(-1);
                else if (dia.DayOfWeek == DayOfWeek.Wednesday)
                    segundaFeira = dia.AddDays(-2);
                else if (dia.DayOfWeek == DayOfWeek.Thursday)
                    segundaFeira = dia.AddDays(-3);
                else if (dia.DayOfWeek == DayOfWeek.Friday)
                    segundaFeira = dia.AddDays(-4);
                else if (dia.DayOfWeek == DayOfWeek.Saturday)
                    segundaFeira = dia.AddDays(-5);
                else if (dia.DayOfWeek == DayOfWeek.Sunday)
                    segundaFeira = dia.AddDays(-6);
            }

            for (int i = 0; i < 7; i++)
            {
                var novaData = segundaFeira;
                var proximaData = i == 0 ? segundaFeira : novaData.AddDays(i);
                dias.Add(proximaData.Date);
            }

            var semana = 1;

            if (dias.Any(c => c.Day >= 1 && c.Day <= 7))
                semana = 1;
            else if (dias.Any(c => c.Day >= 8 && c.Day <= 14))
                semana = 2;
            else if (dias.Any(c => c.Day >= 15 && c.Day <= 21))
                semana = 3;
            else if (dias.Any(c => c.Day >= 22 && c.Day <= 28))
                semana = 4;

            return new Semana { Dias = dias, Numero = semana };
        }

        public List<DateTime> GeraSemana(DateTime dia)
        {
            var dias = new List<DateTime>();

            for (int i = 0; i < 7; i++)
            {
                var novaData = dia;
                var proximaData = i == 0 ? dia : novaData.AddDays(i);
                dias.Add(proximaData.Date);
            }

            return dias;
        }

        public void BindTimeSheet(bool atualizar = false)
        {
            lblDivergencias.Text = "";

            var divHeaderTarefa = AplicaEstilo(new Panel(), "gray", "white", "item_tarefa_header");
            var lblHeaderTarefa = new Label { Text = "TAREFA" };
            divHeaderTarefa.Controls.Add(lblHeaderTarefa);
            timesheet.Controls.Add(divHeaderTarefa);

            if (SemanaAtual == null)
                SemanaAtual = GetSemana(DateTime.Now);

            if (SemanaAtual.Dias.All(c => c.Date.Year != 9999))
                SemanaAtual.Dias.Add(DateTime.MaxValue);

            for (int i = 0; i < SemanaAtual.Dias.Count; i++)
            {
                var dia = SemanaAtual.Dias[i].ToString("dddd", new CultureInfo("pt-BR")).Substring(0, 3).ToUpperInvariant();

                dia = "<div style='font-weight:bold;text-align:center;height:14px;line-height:14px;'>" +
                      SemanaAtual.Dias[i].ToString("dd/MM") + "</div>" +
                      "<div style='font-weight:bold;text-align:center;height:14px;line-height:14px;'>" + dia + "</div>";


                if (SemanaAtual.Dias[i] == DateTime.MaxValue)
                    dia = "<div style='font-weight:bold;text-align:center;height:14px;line-height:14px;'>TOTAL</div>" +
                      "<div style='font-weight:bold;text-align:center;height:14px;line-height:14px;'>SEMANA</div>";

                Panel divPrazo = AplicaEstilo(new Panel(), "gray", "white", "item_header");
                var lblPrazo = new Literal { Text = dia };
                divPrazo.Controls.Add(lblPrazo);
                timesheet.Controls.Add(divPrazo);
            }

            timesheet.Controls.Add(DivClear());

            var usuario = Session["UsuarioSelecionado"] == null
                ? ddlUsuario.SelectedValue
                : (string)Session["UsuarioSelecionado"];

            if (Tarefas == null || atualizar)
            {
                Tarefas = NTimeSheet.ConsultarLista(usuario);
                Tarefas.Add(new TimesheetEntries { workItemId = 0 });
            }

            foreach (var tarefa in Tarefas)
            {
                if (tarefa.TempoNoTFS != tarefa.TempoNaTimeSheet)
                {
                    if (tarefa.TempoNoTFS > tarefa.TempoNaTimeSheet)
                    {
                        lblDivergencias.Text = lblDivergencias.Text +
                            string.Format("<div style='font-size:12px;color:red;border:solid 1px orange;padding:5px;margin:10px;max-width:870px;'>" +
                                          "A Tarefa <strong>\"{0} - {1}\"</strong> tem <strong>{2}</strong> horas no TFS e <strong>{3}</strong> na TimeSheet, " +
                                          "faltam <strong>{4}</strong> para lançar na timesheet.</div>",
                            tarefa.workItemId, tarefa.NomeTarefa, DecimalToTime(tarefa.TempoNoTFS), DecimalToTime(tarefa.TempoNaTimeSheet),
                            DecimalToTime(tarefa.TempoNoTFS - tarefa.TempoNaTimeSheet));
                    }
                    else if (tarefa.TempoNoTFS < tarefa.TempoNaTimeSheet)
                    {
                        lblDivergencias.Text = lblDivergencias.Text +
                            string.Format("<div style='font-size:12px;color:red;border:solid 1px orange;padding:5px;margin:10px;max-width:870px;'>" +
                                          "A Tarefa <strong>\"{0} - {1}\"</strong> tem <strong>{2}</strong> horas na TimeSheet e <strong>{3}</strong> no TFS, " +
                                          "<strong>{4}</strong> estão a mais na timesheet.</div>",
                            tarefa.workItemId, tarefa.NomeTarefa, DecimalToTime(tarefa.TempoNaTimeSheet), DecimalToTime(tarefa.TempoNoTFS),
                            DecimalToTime(tarefa.TempoNaTimeSheet - tarefa.TempoNoTFS));
                    }
                }

                //valida se não tiver apontamento para a data pula para a proxima
                if (!SemanaAtual.Dias.Any(c => tarefa.HorasPorDia.Any(x => x.Data == c.Date)) && tarefa.workItemId != 0)
                    continue;

                //valida se não tiver nenhum apontamento de horas para a semana pula para a proxima
                if (!Tarefas.Any(c => c.HorasPorDia.Any(r => SemanaAtual.Dias.Any(x => x.Date == r.Data.Date) && r.Hora > 0) &&
                    c.workItemId == tarefa.workItemId) && tarefa.workItemId != 0)
                    continue;

                Panel divTarefa = AplicaEstilo(new Panel(),
                    tarefa.workItemId == 0 ? "silver" : "white",
                    "black", "item_tarefa");

                var nomeTarefa = (tarefa.workItemId + " - " + tarefa.NomeTarefa);
                nomeTarefa = nomeTarefa.Length > 30 ? nomeTarefa.Substring(0, 29) + "..." : nomeTarefa;

                var lblTarefa = new Label
                {
                    Text = tarefa.workItemId == 0 ? "TOTAL POR DIA" : nomeTarefa
                    //tarefas.Where(c => c.workItemId == tarefa.workItemId).Sum(x => x.hours).ToString("N2") + " hs]"
                };
                lblTarefa.Style.Add("font-weight", "bold");
                lblTarefa.ToolTip = (tarefa.workItemId + " - " + tarefa.NomeTarefa);
                lblTarefa.Style.Add("cursor", "default");
                divTarefa.Controls.Add(lblTarefa);
                timesheet.Controls.Add(divTarefa);

                for (int i = 0; i < SemanaAtual.Dias.Count; i++)
                {
                    Panel divApontamento = AplicaEstilo(new Panel());

                    if (tarefa.workItemId == 0)
                        divApontamento = AplicaEstilo(new Panel(), "silver", "black", "item_footer");

                    var hora = tarefa.HorasPorDia.FirstOrDefault(c => c.Data.Date == SemanaAtual.Dias[i].Date);

                    var txtApontamento = new TextBox();

                    //aqui calcula o total diario
                    if (tarefa.workItemId == 0)
                    {
                        var totalDia = 0m;
                        foreach (var task in Tarefas)
                        {
                            totalDia = totalDia + task.HorasPorDia.Where(c => c.Data.Date == SemanaAtual.Dias[i].Date).Sum(c => c.Hora);
                        }

                        if (SemanaAtual.Dias[i] == DateTime.MaxValue)
                        {
                            foreach (var task in Tarefas)
                            {
                                totalDia = totalDia + task.HorasPorDia.Where(c => SemanaAtual.Dias.Any(x => x.Date == c.Data.Date)).Sum(c => c.Hora);
                            }
                        }

                        txtApontamento.Text = DecimalToTime(totalDia);
                        txtApontamento.Enabled = false;

                        //formata cor do dia
                        if (totalDia < 8 && SemanaAtual.Dias[i] != DateTime.MaxValue &&
                            SemanaAtual.Dias[i].DayOfWeek != DayOfWeek.Sunday && SemanaAtual.Dias[i].DayOfWeek != DayOfWeek.Saturday)
                            txtApontamento.Style.Add("color", "red");
                        else if (totalDia >= 8 && SemanaAtual.Dias[i] != DateTime.MaxValue)
                            txtApontamento.Style.Add("color", "green");
                        else if (totalDia > 0 && SemanaAtual.Dias[i] != DateTime.MaxValue &&
                            (SemanaAtual.Dias[i].DayOfWeek == DayOfWeek.Sunday || SemanaAtual.Dias[i].DayOfWeek == DayOfWeek.Saturday))
                            txtApontamento.Style.Add("color", "green");

                        //formata cor do totalizador
                        if (totalDia < 40 && SemanaAtual.Dias[i] == DateTime.MaxValue)
                            txtApontamento.Style.Add("color", "red");
                        else if (totalDia >= 40 && SemanaAtual.Dias[i] == DateTime.MaxValue)
                            txtApontamento.Style.Add("color", "green");

                    }
                    //aqui faz o totalizador da tarefa
                    else if (SemanaAtual.Dias[i] == DateTime.MaxValue)
                    {
                        var total = tarefa.HorasPorDia.Where(c => SemanaAtual.Dias.Any(x => x.Date == c.Data.Date)).Sum(c => c.Hora);
                        txtApontamento.Text = DecimalToTime(total);
                        divApontamento.CssClass = "item_total";
                        txtApontamento.Enabled = false;
                    }
                    //aqui faz o apontamento
                    else if (hora != null && hora.Hora > 0)
                    {
                        txtApontamento.Text = DecimalToTime(hora.Hora);
                        txtApontamento.Attributes.Add("chave", string.Format("{0}_{1}", tarefa.workItemId, SemanaAtual.Dias[i].ToString("dd_MM_yyyy")));
                    }
                    else
                        txtApontamento.Attributes.Add("chave", string.Format("{0}_{1}", tarefa.workItemId, SemanaAtual.Dias[i].ToString("dd_MM_yyyy")));

                    txtApontamento.CssClass = "textbox";
                    txtApontamento.Attributes.Add("onkeyup", "MascaraCampo(this,this.event,'HORA')");
                    txtApontamento.Attributes.Add("maxlength", "5");
                    divApontamento.Controls.Add(txtApontamento);

                    timesheet.Controls.Add(divApontamento);
                }

                timesheet.Controls.Add(DivClear());
            }
        }

        public static string DecimalToTime(decimal dHours)
        {
            decimal hours = Math.Floor(dHours); //take integral part
            decimal minutes = (dHours - hours) * 60.0M; //multiply fractional part with 60
            //int D = (int)Math.Floor(dHours / 24);
            //int H = (int)Math.Floor(hours - (D * 24));
            int H = (int)Math.Floor(hours);
            int M = (int)Math.Floor(minutes);
            //int S = (int)Math.Floor(seconds);   //add if you want seconds
            string timeFormat = String.Format("{0:00}:{1:00}", H, M);

            return timeFormat;
        }

        public static decimal TimeToDecimal(string time)
        {
            return (decimal)TimeSpan.Parse(time).TotalHours;
        }

        protected void btnAdicionar_OnClick(object sender, EventArgs e)
        {
            NTimeSheet.Inserir(new TimesheetEntries
            {
                entryDate = Convert.ToDateTime(txtData.Text),
                workItemId = Convert.ToInt32(txtIDTarefa.Text),
                hours = TimeToDecimal(txtTempo.Text),
                sid = Convert.ToInt32(ddlUsuario.SelectedValue).ToString()
            });

            BindTimeSheet(true);

            txtIDTarefa.Text = string.Empty;
            txtNomeTarefa.Text = string.Empty;
            txtData.Text = string.Empty;
            txtTempo.Text = string.Empty;
        }

        protected void ddlUsuario_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            Session["UsuarioSelecionado"] = ddlUsuario.SelectedValue;
            SemanaAtual = null;
            BindTimeSheet(true);

            var cookie = new HttpCookie("user_timesheet")
            {
                Expires = DateTime.Now.AddDays(2),
                Value = ddlUsuario.SelectedValue
            };
            Response.Cookies.Add(cookie);
        }

        protected void btnAnterior_OnClick(object sender, ImageClickEventArgs e)
        {
            if (SemanaAtual != null)
            {
                var dia = SemanaAtual.Dias.Where(c => c.Date.Year != 9999).Min(c => c.Date).AddDays(-6);
                SemanaAtual = GetSemana(dia);
            }
            BindTimeSheet();
        }

        protected void btnProxima_OnClick(object sender, ImageClickEventArgs e)
        {
            if (SemanaAtual != null)
            {
                var dia = SemanaAtual.Dias.Where(c => c.Date.Year != 9999).Max(c => c.Date).AddDays(1);
                SemanaAtual = GetSemana(dia, false);
            }
            BindTimeSheet();
        }

        protected void btnAtualizar_OnClick(object sender, EventArgs e)
        {
            BindTimeSheet(true);
        }
    }
}